/**
 * 创建文件夹: 异步,递归,可中断
 * 		若同步/非递归/不用中断: 使用$.fsMkdir()
 * @param dir string 目录路径
 * @param opt json|string|null 选项
 * 		- string: 内部转为 -> opt={mode:opt}
 * 		mode: string 创建权限  存在不改  默认:'755'
 * @return Promise<string|null> 追加.stop()中断停止
 * 		string:$PATH.resolve(dir), null:中断停止时
 */
$.fsMkdix = function(dir, opt=null){
	const $PATH=require('node:path'), MK=(dir,opt)=>{
		return $.fsAsync('mkdir', dir, opt.mkdir)
			.then(()=>1).catch(e=>CATCH(e,dir,opt));
	};
	const START=$.track(MK), CATCH=(e,dir,o)=>{
		if(o.X) return; if(e.code==='EISDIR') return 1;
		if(e.code==='EEXIST') // 已存在:检测是否文件夹
			return $.fsStat(dir).then(v=>{
				if(v.isDirectory()) return 1; throw e;
			});
		if(e.code==='ENOENT')//上级不存在:创建上级目录
			return MK($PATH.dirname(dir), o)
				.then(()=>o.X?false:MK(dir,o));
		throw e; // 其他异常: 抛出
	};
	$.fsMkdix = function(dir, opt=null){
		if(typeof opt==='string') opt={mode:opt};
		else opt = $.mix({}, {mode:'755'}, opt);
		dir=$PATH.resolve(dir); opt.opx={mode:opt.mode};
		let w = START(dir,opt).then(v=>v?dir:null);
		w = w.catch(e=>opt.X?null:$.err('$.fsMkdix',e));
		opt.X=false;  w.stop=()=>opt.X=true;  return w;
	};
	return $.fsMkdix(dir, opt);
};
